import {findLastIndex} from "lodash"

enum actionType {
  start, line, finished,
}

// 动作类
class Actions {
  records: Array<Action> = []
  painter: CanvasRenderingContext2D
  canvas: HTMLCanvasElement
  background: string = 'rgba(255,255,250,1)'
  isEndLind = false
  prePoint?: Point
  lineWidth = 1.5


  constructor (params: {canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, height?: number, width?: number, background?: string, lineWidth?: number}) {
    this.canvas = params.canvas
    this.painter = params.ctx || this.canvas.getContext('2d')
    params.background && (this.background = params.background)
    params.lineWidth && (this.lineWidth = params.lineWidth)

    this.initBg()
  }
  // 获取step
  _steps () {
    let len = this.records.length
    if (len) {
      let arr: Array<{start: number, end: number}> = []
      let o: {start: number, end: number} | any = {}
      this.records.forEach((action, index) => {
        if (action.type === actionType.start) {
          o.start = index
        }
        if (action.type === actionType.finished) {
          o.end = index
          arr.push(Object.assign({}, o))
          o = {}
        }
      })
      return arr
    }
    return []
  }
  // 添加
  add (action: Action) {
    this.records.splice(this.records.length, 0, action)
  }

  // 重新绘制，可用用back之中
  reDraw () {
    this.painter.lineWidth = this.lineWidth
    const steps = this._steps()
    if (steps.length > 0) {
      this.initBg()
      for (let stpe of steps) {
        const actions = this.records.slice(stpe.start, stpe.end + 1)
        for (let _action of actions) {
          switch (_action.type) {
            case actionType.start:
              this.painter.beginPath()
              this.painter.moveTo(...(_action.point as [ number, number ]))
              break;
            case actionType.finished:
              this.painter.stroke()
              break;
            default:
              this.painter.lineTo(...(_action.point as [ number, number ]))
          }
        }
      }
    }
  }

  // 回退一步
  back () {
    if (this.records.length > 0) {
      const steps = this._steps()
      const len = steps.length - 1
      if (len === 0) {
        return this.clear()
      }
      const lastStep = steps[ len - 1 ]
      this.records = this.records.slice(0, lastStep.end + 1)
      this.reDraw()
    }
  }

  private _wipeOver () {
    this.painter.clearRect(0, 0, this.canvas.width, this.canvas.height)
    this.initBg()
  }

  //绘制方法
  draw (action: Action) {
    const none = this.records.length === 0
    const hasOne = this.records.length === 1 && this.records[ 0 ].type === actionType.start

    // 如果有一个则设置
    if (hasOne) {
      this.prePoint = this.records[ 0 ].point
    }
    // 如果没有或者只有一个且是start则返回
    if (none || hasOne) return

    const temp = Object.assign({}, this.prePoint)
    const point = (action.point as Point)
    this.prePoint = point
    this.painter.lineWidth = this.lineWidth

    switch (action.type) {
      case actionType.start:
        break
      case actionType.finished:
        const steps = this._steps()
        this._drawFragment(steps[ steps.length - 1 ])
        break;
      default:
        this.painter.beginPath()
        this.painter.moveTo(temp.x, temp.y)
        this.painter.lineTo(point.x, point.y)
        this.painter.stroke()
    }
  }

  // 绘制片断
  private _drawFragment (fragment: {start: number, end: number}) {
    const points = this.records.slice(fragment.start, fragment.end + 1)
    this.painter.lineWidth = this.lineWidth
    points.forEach(action => {
      const point = (action.point as [ number, number ])
      switch (action.type) {
        case actionType.start:
          this.painter.beginPath()
          this.painter.moveTo(...point)
          break
        case actionType.finished:
          this.painter.lineTo(...point)
          this.painter.stroke()
          break;
        default:
          this.painter.lineTo(...point)
      }

    })

  }
  // 初始化背景
  initBg () {
    const ctx = this.painter
    ctx.fillStyle = this.background
    ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
  }
  // 清除画布
  clear (keep = false) {
    this.records = []
    this._wipeOver()
  }
}

// 动作
class Action {
  type: actionType
  point?: Point
  constructor (type: actionType, point?: Point) {
    this.type = type
    this.point = point
  }
}

// 点
class Point extends Array<number> {
  [ 0 ]: number
  [ 1 ]: number
  x: number
  y: number
  constructor (x: number, y: number) {
    super(2)
    this[ 0 ] = this.x = x
    this[ 1 ] = this.y = y
  }
}

export {
  Action,
  Point,
  actionType
}

export default Actions
